import axios from 'axios'
import { REQUEST, RESPONSE } from '@/config'

// 常见错误信息
export const errorCode = {
  401: '认证失败，无法访问系统资源',
  403: '当前操作没有权限',
  404: '访问资源不存在',
  default: '系统未知错误，请反馈给管理员'
}

// 生成错误与接口统一返回格式一致
export function cError(msg = '', code = RESPONSE.ERROR_CODE) {
  return { success: false, msg: msg || '发生错误', code: code, data: null }
}

// 同一请求超时进行取消
export const pendingMap = new Map()

axios.defaults.headers['Content-Type'] = 'application/json;charset=utf-8'

let axiosConfig = {
  baseURL: REQUEST.DOMAIN + REQUEST.API_PREFIX,
  timeout: 10000
}

const service = axios.create(axiosConfig)

/**
 * http request 拦截器
 */
service.interceptors.request.use(
  config => {
    // 去除重复的开头，可能多次拼接baseUrl
    let url = config.url
    if (axiosConfig.baseURL && url.startsWith(axiosConfig.baseURL)) {
      config.url = url.replace(axiosConfig.baseURL, '')
    }
    if ('cancelToken' in config || 'signal' in config) return config
    // 多次请求，取消上次
    const pendingKey = JSON.stringify({
      url: config.url || '',
      data: config.data || '',
      params: config.params || ''
    })
    const cancelFunc = pendingMap.has(pendingKey) ? pendingMap.get(pendingKey) : ''
    if (!axios.CancelToken) {
      typeof cancelFunc === 'function' && cancelFunc('canceled')
      config.cancelToken = new axios.CancelToken(cancel => {
        pendingMap.set(pendingKey, cancel)
      })
    } else {
      typeof cancelFunc.abort === 'function' && cancelFunc.abort()
      const cancelObj = new AbortController()
      config.signal = cancelObj.signal
      pendingMap.set(pendingKey, cancelObj)
    }
    return config
  },
  error => {
    return Promise.reject(error)
  }
)
/**
 * http response 拦截器
 */
service.interceptors.response.use(
  response => {
    if (response.status !== 200) {
      return Promise.reject(new Error('网络请求失败：' + (response.statusText || response.status)))
    }
    return Promise.resolve(response)
  },
  error => {
    return Promise.reject(error)
  }
)

service.isCancel = v => axios.isCancel(v)

export default service
